#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project ：python_learning 
@File ：建造者模式.py
@IDE  ：PyCharm 
@Author ：李涵彬
@Date ：2024/3/1 17:55 
"""

"""
建造者模式 (Builder Pattern)
建造者模式是一种创建型设计模式，用于构建复杂对象。它允许您按照步骤构建对象，同时隐藏构建细节。建造者模式将构建过程与最终对象的表示分离开来，使得同样的构建过程可以创建不同的表示。

在 Python 中，建造者模式通常通过一个 Director 类来控制建造过程，以及一个 Builder 接口和具体的 Builder 类来实现具体的构建步骤。以下是一个简单的示例：

在这个示例中，我们定义了产品类 Product，以及抽象建造者类 Builder，其中包含了构建产品的抽象方法。然后定义了两个具体建造者类 ConcreteBuilder1 和 ConcreteBuilder2，每个具体建造者类都实现了构建产品的具体步骤。

指挥者类 Director 控制了建造过程，它接受一个具体建造者对象作为参数，并按照预定的步骤来构建产品。

在客户端代码中，我们可以选择使用不同的具体建造者来构建产品。这种方式使得构建过程与产品的表示分离，使得系统更易于扩展和维护。
"""

from abc import ABC, abstractmethod


# 产品类
class Product:
	def __init__(self):
		self.parts = []

	def add(self, part):
		self.parts.append(part)

	def list_parts(self):
		return f"产品部件: {', '.join(self.parts)}"


# 抽象建造者
class Builder(ABC):
	@abstractmethod
	def build_part_a(self):
		pass

	@abstractmethod
	def build_part_b(self):
		pass

	@abstractmethod
	def get_result(self) -> Product:
		pass


# 具体建造者1
class ConcreteBuilder1(Builder):
	def __init__(self):
		self.product = Product()

	def build_part_a(self):
		self.product.add("部件A")

	def build_part_b(self):
		self.product.add("部件B")

	def get_result(self) -> Product:
		return self.product


# 具体建造者2
class ConcreteBuilder2(Builder):
	def __init__(self):
		self.product = Product()

	def build_part_a(self):
		self.product.add("部件X")

	def build_part_b(self):
		self.product.add("部件Y")

	def get_result(self) -> Product:
		return self.product


# 指挥者
class Director:
	def __init__(self, builder: Builder):
		self.builder = builder

	def construct(self):
		self.builder.build_part_a()
		self.builder.build_part_b()


if __name__ == "__main__":
	# 使用具体建造者1构建产品
	builder1 = ConcreteBuilder1()
	director1 = Director(builder1)
	director1.construct()
	product1 = builder1.get_result()
	print(product1.list_parts())  # 输出：产品部件: 部件A, 部件B

	# 使用具体建造者2构建产品
	builder2 = ConcreteBuilder2()
	director2 = Director(builder2)
	director2.construct()
	product2 = builder2.get_result()
	print(product2.list_parts())  # 输出：产品部件: 部件X, 部件Y
